﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AzureGames.Data;
using AzureGames.Domain.Contracts;
using AzureGames.Domain.Models;
using AzureGames.Model;
using AzureGames.Model.Statistics;

namespace AzureGames.Domain.Handlers
{
    /// <summary>
    /// Creates a new game board
    /// </summary>
    /// <remarks>this is used to start a new single player game or a game that should wait for specificly invited players</remarks>
    public class CreateNewGame
    {
        private readonly IBoardRepository _boardRepository;
        private readonly IGameDefinitionRepository _gameDefintionRepository;
        private readonly IPlayerRepository _playerRepository;
        private readonly IUserStatisticsRepository _userstatisticsRepository;
        private readonly IGameStatisticsRepository _gamestatisticsRepository;

        public CreateNewGame(IBoardRepository gameBoardRepository, IGameDefinitionRepository gameDefinitionRepository, IPlayerRepository playerRepository, IUserStatisticsRepository userstatisticsRepository, IGameStatisticsRepository gamestatisticsRepository)
        {
            _boardRepository = gameBoardRepository;
            _gameDefintionRepository = gameDefinitionRepository;
            _playerRepository = playerRepository;
            _gamestatisticsRepository = gamestatisticsRepository;
            _userstatisticsRepository = userstatisticsRepository;
        }

        public virtual GameBoard Execute(int gameDefinitionID, List<string> playerIDs)
        {
            try
            {
                var gameDefinition = _gameDefintionRepository.GetGameDefinition(gameDefinitionID);

                // retrieve players
                var players = new List<Player>();
                foreach (var playerID in playerIDs)
                {
                    players.Add(_playerRepository.GetPlayer(playerID));
                }

                // for now this is hard coded to create a game 
                var board = new Board
                {
                    ID = Guid.NewGuid(),
                    GameDefinitionID = gameDefinitionID,
                    PlayerIDs = playerIDs,
                    State = 0,
                    Value = 0,
                    Properties = gameDefinition.StartingProperties,
                };

                // only add for members                
                if (playerIDs[0] != Guid.Empty.ToString())
                {
                    _boardRepository.AddGameBoard(board);
                }

                if (board.PlayerIDs.Count == gameDefinition.RequiredNumberOfPlayers)
                {
                    board.State = Board.Active;

                    if (playerIDs[0] != Guid.Empty.ToString())
                    {
                        _boardRepository.UpdateGameBoard(board);
                        _gamestatisticsRepository.AddGameStatistic(gameDefinitionID, GameType.MultiplePlayer, DateTime.Now.Date, Board.Created);
                    }

                    foreach (var player in players)
                    {
                        if (player is AIPlayer)
                            gameDefinition.JavascriptFiles.Add(((AIPlayer)player).ResourceID);

                        if (player is User)
                            _userstatisticsRepository.AddUserStatistic(gameDefinitionID, GameType.MultiplePlayer, DateTime.Now.Date, player.ID, Board.Created);
                    }

                }

                return new GameBoard(gameDefinition, board, new List<GamePlayer>(players.Select(p => new GamePlayer(p))));
            }
            catch (InvalidOperationException e)
            {
                throw new BusinessServicesException("Unable to retrieve game board from database.", e);
            }
        }
    }
}
